const log = console.log.bind(console)

const ensure = function (condition, message) {
    if (!condition) {
        log('测试失败', message)
    } else {
        log('测试成功')
    }
}



const isArray = (o) => Array.isArray(o)

const isObject = (o) => Object.prototype.toString.call(o) === '[object Object]'

const arrayEquals = function (a, b) {
    if (!isArray(a) || !isArray(b)) {
        log("数据中一个不是数组")
        log("result", a)
        log("expect", b)
        return false
    }
    if (a.length !== b.length) {
        log("数组长度不等")
        log("result", a)
        log("expect", b)
        return false
    }
    for (let i = 0; i < a.length; i += 1) {
        const e = equals(a[i], b[i])
        if (!e) {
            log("数组下的元素不等")
            log("result", a[i])
            log("expect", b[i])
            return false
        }
    }
    return true
}

const objectEquals = function (a, b) {
    if (!isObject(a) || !isObject(b)) {
        log("数据中一个不是对象")
        log("result", a)
        log("expect", b)
        return false
    }
    const keys1 = Object.keys(a)
    const keys2 = Object.keys(b)

    if (keys1.length !== keys2.length) {
        log("对象长度不等")
        log("result", a)
        log("expect", b)

        return false
    }

    for (let i = 0; i < keys1.length; i += 1) {
        const k1 = keys1[i]
        const v1 = a[k1]

        const k2 = keys2[i]
        const v2 = b[k1]

        if (!keys2.includes(k1)) {
            log("key不匹配")
            log("result", k1)
            log("expect", k2)
            return false
        } else {
            const e = equals(v1, v2)
            if (!e) {
                log("对象下的元素不等，此时的key是", k1)
                log("result", v1)
                log("expect", v2)
                return false
            }
        }
    }
    return true
}

const equals = (a, b) => {
    // log("## equals")
    // log("result", a)
    // log("expect", b)
    if (isObject(a) && isObject(b)) {

        return objectEquals(a, b)
    } else if (isArray(a) && isArray(b)) {

        return arrayEquals(a, b)
    } else {
       if(a !== b){
            log("单个元素不相等或者类型不同")
            log("result", a)
            log("expect", b)
        }
        return a === b
    }
}

const arrayDeepClone = function (array) {
    let output = []
    for (let i = 0; i < array.length; i++) {
        const e = array[i]
        const d = deepClone(e)
        output.push(d)
    }
    return output
}

const objectDeepClone = (o) => {
    // 遍历所有key，然后复制
    let output = {}
    const keys = Object.keys(o)
    for (let i = 0; i < keys.length; i += 1) {
        const k = keys[i]
        const v = o[k]
        const r = deepClone(v)
        output[k] = r
    }
    return output
}

const deepClone = (o) => {
    if (isObject(o)) {
        return objectDeepClone(o)
    } else if (isArray(o)) {
        return arrayDeepClone(o)
    } else {
        return o
    }
}

const flat = (array) => {
    let output = []
    for (let i = 0; i < array.length; i++) {
        const e = array[i]
        if (isArray(e)) {
            const t = flat(e)
            for (let j = 0; j < t.length; j++) {
                output.push(t[j])
            }
        } else {
            output.push(e)
        }
    }
    return output
}

